<?php
declare (strict_types=1);

namespace app\user\model\user;

use app\common\logic\Attach;
use app\common\model\{BaseModel, ShareCode};
use app\school\logic\school\School;
use app\user\event\subscribes\user\Account as UserSubscribe;
use think\facade\Event;
use think\helper\Str;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;

/**
 * 定义用户数据模型
 */
class Account extends BaseModel
{
    use SoftDelete;

    /**
     * 表名
     *
     * @var string
     */
    protected $name = 'user';

    /**
     * 追加关联属性
     *
     * @var array
     */
    // protected $append = ['avatarUrl'];

    /**
     * 设置自动写入时间
     *
     * @var boolean
     */
    protected $autoWriteTimestamp = true;

    /**
     * 设置隐藏字段
     *
     * @var array
     */
    protected $hidden = ['password', 'salt'];

    /**
     * 定义字段类型
     *
     * @var array
     */
    protected $type = [
        'id'              => 'integer',
        'status'          => 'integer',
        'last_login_time' => 'integer',
        'gender'          => 'integer',
        'avatar'          => 'integer',
        // 'phone'           => 'integer',
        'delete_time'     => 'integer',
        'create_time'     => 'integer',
        'update_time'     => 'integer',
    ];

    /**
     * 定义表主键
     *
     * @var string
     */
    protected $pk = 'id';

    /* 模型事件 */
    /**
     * 新增数据事件
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     *
     * @return   string
     */
    public static function onBeforeInsert($user)
    {
        // 机构ID
        $mhm_id = $user->getAttr('mhm_id') ?: intval(request()->mhm_id);
        // 自动填充注册IP
        $user->register_ip = request()->ip();
        // 用户来源
        $user->register_device = request()->device_type;
        // 填充用户名
        $str             = Str::random(4);
        $user->user_name = $user->phone . '_' . $str;
        $user->nick_name = '用户' . $user->phone . '_' . $str;
        $user->status    = 1;
        $user->mhm_id    = $mhm_id;
        // 分享信息
        $user->superior_user_id = ShareCode::getShareUser();
    }

    /**
     * 创建用户之后
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param    [type]                         $user [description]
     * @return void [type]                               [description]
     */
    public static function onAfterInsert($user)
    {
        trace($user, 'info');
        Event::subscribe(UserSubscribe::class);
        $user->credit_key = 'register';
        $user->rel_pk     = $user->id;
        Event::trigger('UserReg', $user);
        // Event::trigger('UserCreated');
    }

    /**
     * 修改用户之后
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param    [type]                         $user [description]
     * @return void [type]                               [description]
     */
    public static function onAfterUpdate($user)
    {
        Event::subscribe(UserSubscribe::class);
        Event::trigger('UserUpdated', $user);
    }

    /**
     * 成功删除之后
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param    [type]                         $user [description]
     * @return void [type]                               [description]
     */
    public static function onAfterDelete($user)
    {
        // Event::subscribe(UserSubscribe::class);
        // Event::trigger('UserDeleted', $user);
    }

    /* 获取器 */
    /**
     *  获取用户状态显示文字
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     *
     * @param string $value
     * @param        $data
     * @return string
     */
    public function getStatusTextAttr($value = '', $data): string
    {
        return $data['status'] == 1 ? '正常' : '禁用';
    }

    public function getLastLoginIpAttr($value): string
    {
        return $value ?: '';
    }

    public function getLastLoginTimeAttr($value): int
    {
        return $value ?: 0;
    }

    public function getDeleteTimeAttr($value): int
    {
        return $value ?: 0;
    }

    public function getSignatureAttr($value): string
    {
        return $value ?: "这个人很懒，什么都没有留下！";
    }

    /**
     * 注册来源
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-05-06
     *
     * @param string $value [description]
     * @return string [type]                                [description]
     */
    public function getRegisterDeviceAttr($value = '')
    {
        return $value ?: 'Unknown';
    }

    /**
     * 密码转为小写
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-14
     *
     * @param    [type]                         $value [description]
     * @return string [type]                                [description]
     */
    public function getPasswordAttr($value): string
    {
        return strtolower($value);
    }

    /* 修改器 */
    /**
     * 设置密码密钥
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     */
    protected function setSaltAttr($value = '', $data): string
    {
        return 'pwd_' . mt_rand(100000, 999999);
    }

    /**
     * 加密密码
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-03
     */
    protected function setPasswordAttr($value = '', $data): string
    {
        // 触发设置密码密钥的方法
        $this->setAttr('salt', '');

        return $this->makePassword($value, $this->salt);
    }

    /**
     * 密码处理
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param $password
     * @param $salt
     * @return string [type]                                   [description]
     */
    protected function makePassword($password, $salt): string
    {
        return md5(md5(strtolower($password)) . md5($salt));
    }

    /* 查询范围 */
    /**
     * 设置状态查询条件
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     *
     * @param    [type]                         $query  [description]
     * @param integer $status 查询条件值
     */
    public function scopeStatus($query, $status = 1)
    {
        $query->where('status', $status);
    }

    /* 关联 */
    // 头像URL
    public function avatarUrl()
    {
        return $this->belongsTo(Attach::class, 'avatar')->bind(['avatar_url' => 'fileurl']);
    }

    // 余额
    public function balance()
    {
        return $this->hasOne(Balance::class, 'user_id')->bind(['balance']);
    }

    // 收入
    public function income()
    {
        return $this->hasOne(Income::class, 'user_id')->bind(['income']);
    }

    // 余额
    public function credit()
    {
        return $this->hasOne(Credit::class, 'user_id')->bind(['credit']);
    }

    // 会员
    public function vip()
    {
        return $this->hasOne(VipUser::class, 'user_id')->bind(['vip_expire_time' => 'expire_time']);
    }

    // 消息通知
    public function notifyCount()
    {
        return $this->hasMany(NotifyMessage::class, 'user_id')->where('is_read', 0);
    }

    public function schoolBasic()
    {
        return $this->belongsTo(School::class, 'mhm_id')->bind(['school_name' => 'title', 'school_id' => 'id']);
    }

    public static function unnecessaryField()
    {
        return ['register_device', 'password', 'salt', 'register_ip', 'last_login_ip', 'delete_time', 'create_time', 'update_time'];
    }

    /**
     * 用户是否被关注，用于当前用户进入他人主页使用
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-16
     *
     * @return boolean [description]
     */
    public function hasBeenFollowed()
    {
        return $this->hasOne(Follow::class, 'follow_user_id')->where('user_id', request()->mid);
    }

    /**
     * 用户关注数
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-16
     *
     * @return HasMany [type]        [description]
     */
    public function followingNum()
    {
        return $this->hasMany(Follow::class, 'user_id');
    }

    /**
     * 用户粉丝数
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-16
     *
     * @return HasMany [type]        [description]
     */
    public function fansNum()
    {
        return $this->hasMany(Follow::class, 'follow_user_id');
    }

    /**
     * 最近访客数
     * Author 亓官雨树<lucky.max@foxmail.com>
     * Date 2021-06-16
     *
     * @return HasMany [type] [description]
     */
    public function recentVisitorNum()
    {
        return $this->hasMany(Visitor::class, 'visit_user_id')->where('update_time', '>', time() - 86400 * 7);
    }
}
